//
//  sinaWidgetDemo.swift
//  sinaWidgetDemo
//
//  Created by Xueming on 2022/1/18.
//

import WidgetKit
import SwiftUI
import Intents

/*
 遵守TimelineProvider协议，产生一个时间线，告诉 WidgetKit 何时渲染与刷新 Widget，时间线包含一个你定义的自定义TimelineEntry类型。时间线条目标识了你希望WidgetKit更新Widget内容的日期。在自定义类型中包含你的Widget的视图需要渲染的属性。
 */
struct Provider: IntentTimelineProvider {
    
    var poster:Poster = Poster(author: "王学明", content: "太天真")
    // 占位视图 提供一个默认的视图，例如网络请求失败、发生未知错误、第一次展示小组件都会展示这个view
    func placeholder(in context: Context) -> PosterEntry {
        let entry = PosterEntry(date: Date(), poster: poster, configuration: ConfigurationIntent())
        return entry
    }
    // 编辑屏幕在左上角选择添加Widget、第一次展示时会调用该方法
    //为了在小部件库中显示小部件，WidgetKit要求提供者提供预览快照，在组件的添加页面可以看到效果
    func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (PosterEntry) -> Void) {
        let entry = PosterEntry(date: Date(), poster: poster, configuration: ConfigurationIntent())
        completion(entry)
    }
    // 进行数据的预处理，转化成Entry
    //在这个方法内可以进行网络请求，拿到的数据保存在对应的entry中，调用completion之后会到刷新小组件
    //参数policy：刷新的时机
    //.never：不刷新
    //.atEnd：Timeline 中最后一个 Entry 显示完毕之后自动刷新。Timeline 方法会重新调用
    //.after(date)：到达某个特定时间后自动刷新
    // !!!: Widget 刷新的时间由系统统一决定，如果需要强制刷新Widget，可以在 App 中使用 WidgetCenter 来重新加载所有时间线：WidgetCenter.shared.reloadAllTimelines()
    func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<PosterEntry>) -> Void) {
        print("需要刷新")
        let currentDate = Date()
        //设定多少时间更新一次数据
        let updateDate = Calendar.current.date(byAdding: .hour, value: 1, to: currentDate)!
        
        PosterData.getTodayPoster { result in
            let poster1: Poster
            if case .success(let fetchedData) = result{
//                print("刷新了")
                poster1 = fetchedData
            }else{
                poster1=Poster(author: "Now", content: "Now格言");
            }
            
            var entries: [PosterEntry] = []
//            for offset in 0..<5 {
//                print("xunhuan = " + String(offset))
                let entryDate = Calendar.current.date(byAdding: .hour, value: 1, to: currentDate)!
                let entry = PosterEntry(date: entryDate, poster: poster1, configuration: configuration)
                entries.append(entry)
//            }
            let timeline1 = Timeline(entries: entries, policy: .after(updateDate))
            completion(timeline1)
        }
    }
}

//struct SimpleEntry: TimelineEntry {
//    let date: Date
//    let configuration: ConfigurationIntent
//}

struct sinaWidgetDemoEntryView : View {
    var entry: Provider.Entry
    @Environment(\.widgetFamily) var family // 尺寸环境变量
    //针对不同尺寸的 Widget 设置不同的 View
    //    多Widget组件实现
    //    一个Widget只能实现大中小三个不同尺寸的组件形式，如果现有需求要做不同功能并且相同尺寸规格的组件则需要实现多组件
    //
    //    1.通过修改原Widget入口文件方法添加更多配置来支持多个Widget
    //    2.另建SwiftUI文件实现组件功能，并去除@main，修改相同函数名
    //    @ViewBuilder
    var body: some View {
        
        //        switch family {
        //        case .systemSmall:
        //            // 小尺寸
        //            Text(entry.date, style: .time)
        //
        //        case .systemMedium: break
        //
        //            // 中尺寸
        //        default: break
        //            // 大尺寸
        //
        //        }
        //!!!: 页面搭建展示
        //ZStack使用，类似安卓里面的FrameLayout，可以重叠布局
        //常用容器组件HStack使用，水平方向布局
        //常用容器组件VStack使用，垂直方向布局
        ZStack{
           
            Image(uiImage: entry.poster.posterImage!)
                .resizable()
                .frame(minWidth: 169, maxWidth: .infinity, minHeight: 169, maxHeight: .infinity, alignment: .center)
                .scaledToFill()
                .edgesIgnoringSafeArea(.all)
                .aspectRatio(contentMode: .fill)
            Text(entry.poster.content)
                .foregroundColor(Color.white)
                .lineLimit(4)
                .font(.system(size: 14))
                .padding(.horizontal)
            
//            if #available(iOSApplicationExtension 15.0, *) {
            Text(entry.date, style: .time).background(Color(hexString: "#FFFF00")).frame(width: 60, height: 20, alignment: .center).shadow(color: .blue, radius: 15, x: 4, y: 7).border(.blue, width: 1).foregroundColor(.black).lineLimit(1).font(.system(size: 13)).cornerRadius(1).offset(x: 0, y: 45)
//            } else {
//                // Fallback on earlier versions
//            }
        
        
            
        }
        .widgetURL(URL(string: "urlschema://sinaDemoWidgetLink"))
        
    }
}
extension Color {
    
    //#ARGB
    init?(hexString: String) {
        var hex = hexString;
        guard hexString.starts(with: "#") else {
            return nil
        }
        hex.remove(at: hexString.startIndex)
        var value: UInt64 = 0
        Scanner(string: hex).scanHexInt64(&value)

        var a = 0xFF / 255.0
        if hex.count > 7 {
            a = Double(value >> 24) / 255.0
        }
        let r = Double((value & 0xFF0000) >> 16) / 255.0;
        let g = Double((value & 0xFF00) >> 8) / 255.0;
        let b = Double(value & 0xFF) / 255.0
        self.init(red: Double(r), green: Double(g), blue: Double(b))
        _ = self.opacity(Double(a))
    }
}
//@main：代表着Widget的主入口，系统从这里加载，可用于多Widget实现
@main
struct GameWidgets: WidgetBundle {

    @WidgetBundleBuilder
    var body: some Widget {
        // !!!: 注意啦🌶
        /*
         如果不能直接运行调试，那么是因为没有找到默认的组件，只剩一个就可以了。别的注释掉。
         如果第一次运行，不显示图片，控制台输出没有网络，是因为主app没有允许联网，需要运行一下主app，点击一下登录按钮，允许互联网链接。
         */
        XMWidgetCalendar()
        XMWidgetClock()
        sinaWidgetDemo()
    }
}
//kind：是Widget的唯一标识
//WidgetConfiguration：初始化配置代码
struct sinaWidgetDemo: Widget {
    let kind: String = "sinaWidgetDemo"
    
    var body: some WidgetConfiguration {
        /*StaticConfiguration : 可以在不需要用户任何输入的情况下自行解析，可以在 Widget 的 App 中获 取相关数据并发送给 Widget
         IntentConfiguration： 主要针对于具有用户可配置属性的Widget
         ，依赖于 App 的 Siri Intent，会自动接收这些 Intent 并用于更新 Widget，用于构建动态 Widget
         configurationDisplayName：添加编辑界面展示的标题
         description：添加编辑界面展示的描述内容
         supportedFamilies：设置Widget支持的控件大小，不设置则默认三个样式都实现
         Widget控件尺寸大小
         屏幕尺寸(portrait)    Small widget    Medium widget    Large widget
         414x896 pt    169x169 pt    360x169 pt    360x376 pt
         375x812 pt    155x155 pt    329x155 pt    329x345 pt
         414x736 pt    159x159 pt    348x159 pt    348x357 pt
         375x667 pt    148x148 pt    322x148 pt    322x324 pt
         320x568 pt    141x141 pt    291x141 pt    291x299 pt
         */
        IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
            sinaWidgetDemoEntryView(entry: entry)
        }
        .configurationDisplayName("sinaDemo Widget")
        .description("This is an example widget.")
    }
}

struct sinaWidgetDemo_Previews: PreviewProvider {
    //屏幕上 Widget 显示的内容，可以针对不同尺寸的 Widget 设置不同的 View。
    static var previews: some View {
        let poster:Poster = Poster(author: "王学明", content: "太天真")
        sinaWidgetDemoEntryView(entry: PosterEntry(date: Date(), poster: poster, configuration: ConfigurationIntent()))
            .previewContext(WidgetPreviewContext(family: .systemMedium))
    }
}
